/*
 *  VortMesh.h
 *  VortPan
 *
 *  Created by Gregor Veble on 6/29/10.
 *  Copyright 2010  . All rights reserved.
 *
 */

#ifndef VORTMESH_H
#define VORTMESH_H

#include <map>
#include <string>

#include "VortPolygonReference.h"
#include "VortPolygon.h"
#include "VortEdge.h"
#include "VortSymmetryPlane.h"

namespace VortPan {
	
	
	typedef std::vector<VortPolygon> PolygonVector;
	typedef std::vector<VortPoint> PointVector;
	typedef std::vector<VortPolygonReference> PolygonReferenceVector;
	typedef std::vector<VortSymmetryPlane> SymmetryPlaneVector;
	
	inline SymmetryPlaneVector DefaultPlanesVector(){
		SymmetryPlaneVector PV;
		return PV;
	}

	struct VortEdgeInfo {
		PolygonReferenceVector PolygonReferences;
		bool Problematic;
	};

	typedef std::map<VortEdge,VortEdgeInfo> EdgeMap;
	
	
	
	class VortMesh : public VortBase {
	public:
		VortMesh();
		VortMesh(const VortMesh& Other);
		~VortMesh();
		
		int LoadPLY(std::string FName, bool WakeMesh=false, re ScaleFactor=ONE);
		int SavePLY(std::string FName);
		

		int ImportRawData(std::string FName, bool WakeMesh=false, re ScaleFactor=ONE, int IndOffset=0, bool OnlyPos=false);
		
		int ExportMathematicaList(std::string FName);
		int ExportCenterPoints(std::string FName);
		int ExportBadEdges(std::string FName);
		
		void AddSimplePolygon(std::vector<Vector3D>& CornerList);
		void FinishSimple();
		
		int Weld(re Eps=0);
		int Mirror(VortSymmetryPlane Plane=DefaultPlane());
		
		VortPointReference AddPoint(const VortPoint& P);
		int AddPointPolygon(VortPolygon& P);
		void RenewAllPointReferences();
		
		int AddMesh(VortMesh& Other);
		
		void Clear();
		
		VortPointReference GetPointReference(int index);
		
		void BuildEdges();
		int CheckEdges(bool Symmetric=false, re Eps=0, SymmetryPlaneVector SymmetryPlanes=DefaultPlanesVector());
		
		void CalculateMeshDerivative(std::vector<re>& Field, std::vector<Vector3D>& Derivative, re Parallel=0.3);
		void CalculateMeshDerivativeLMS(std::vector<re>& Field, std::vector<Vector3D>& Derivative);
		

		
		void ReplaceAllWakePolys(Vector3D Direction, re StartSegment, re EndDistance, re Factor, re Eps=1e-4);
		

		VortMesh& operator=(const VortMesh& Mesh);
	protected:
		int Bake();
		int LabelSolids();

		int GetPointIndex(const VortPointReference& P); //returns -1 if not found
		
		void ReplaceWakePoly(VortEdge Edge, VortEdgeInfo& EdgeInfo, Vector3D Direction, re StartSegment, re EndDistance, re Factor);
		void RecalculateCenters(re Eps=1e-5);
		
		PolygonVector PolygonStorage;
		PointVector PointStorage;
		EdgeMap EdgeStorage;
		
		bool Baked;
		
		int NSolids;		

		friend class VortSystem;
		
	};
	
}

#endif
